package event

import (
	"encoding/json"
	"fmt"
	"strconv"
	"sync"
    
    "collecter/app/common/enum"
    "collecter/app/common/helper"
    "collecter/app/event/interfaces"
)

// 事件通道数据类型 event chan type
type ECType struct {
	EventName   string
	SubjectId   int64
	ExtraParams string
}

// 事件通知通道
var eventChans chan *ECType

/*
 *  InitEventListener
 * @Description: 初始化事件监听
 */
func InitEvent() {
	fmt.Println("事件监听初始化 ... ")
	eventChans = make(chan *ECType, enum.EVENT_CHAN_SIZE)
	go func() {
		wg := sync.WaitGroup{}
		for eventChan := range eventChans {
			// fmt.Printf("eventListener: %+v, type: %T\n", eventListener, eventListener)
			if len(eventChan.EventName) == 0 || eventChan.SubjectId <= 0 || len(eventConfigs) == 0 {
				logMsg := "事件参数错误：{event_name:" + eventChan.EventName + ", subject_id:" +
					strconv.Itoa(int(eventChan.SubjectId)) + ", extra_params: " + eventChan.ExtraParams + "}"
				helper.Logger.WithField("apart", "event").Errorln(logMsg)
				continue
			}
			wg.Add(1)
			// 当前事件执行实例
			if eventInstances, ok := eventConfigs[eventChan.EventName]; !ok {
				continue
			} else {
				// fmt.Printf("eventInstance1: %+v, type: %T\n", eventInstances, eventInstances)
				for _, eventInstance := range eventInstances {
					// fmt.Printf("eventInstance2: %+v, type: %T\n", eventInstance, eventInstance)
					go func(eventInstance interfaces.EventInterfacer, event *ECType) {
						instance := eventInstance.SetValue(event.EventName, event.SubjectId, event.ExtraParams)
						if err := instance.Handle(); err != nil {
							s, _ := json.Marshal(instance)
							logMsg := "事件执行出错。params：" + string(s)
							helper.Logger.WithField("apart", "event").Errorln(logMsg)
							wg.Done()
							return
						}
						instance = nil
						wg.Done()
					}(eventInstance, eventChan)
				}
			}
			wg.Wait()
		}
	}()
	return
}

/**
*  Trigger
*  @Description: 事件触发函数
*  @param eventName 事件名称
*  @param subjectId 主体id，如果是订单相关事件则是订单id，如果是会员相关事件，则是会员id ...
*  @param extraParams 事件处理逻辑需要的其他额外参数，序列化为json字符串后传递，在处理逻辑内按照各自需求自行处理
*  @return bool
 */
func Trigger(eventName string, subjectId int64, extraParams string) {
	var eventParams = ECType{
		EventName:   eventName,
		SubjectId:   subjectId,
		ExtraParams: extraParams,
	}
	eventChans <- &eventParams

	logMsg := "  事件【" + eventName + "】已经触发"
	helper.Logger.WithField("apart", "event").Infoln(logMsg)
}
